home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / xvisrc.zip / SUNFRONT.C < prev    next >
C/C++ Source or Header  |  1992-07-28  |  7KB  |  316 lines

  1. #ifndef lint
  2. static char *sccsid = "@(#)sunfront.c    2.1 (Chris & John Downey) 7/29/92";
  3. #endif
  4.  
  5. /***
  6.  
  7. * program name:
  8.     xvi
  9. * function:
  10.     PD version of UNIX "vi" editor, with extensions.
  11. * module name:
  12.     sunfront.c
  13. * module function:
  14.     Terminal interface module for SunView: front end program.
  15. * history:
  16.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  17.     Originally by Tim Thompson (twitch!tjt)
  18.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  19.     Heavily modified by Chris & John Downey
  20. ***/
  21.  
  22. #include "xvi.h"
  23.  
  24. #include <suntool/sunview.h>
  25. #include <suntool/panel.h>
  26. #include <suntool/icon.h>
  27. #include <suntool/canvas.h>
  28. #include <suntool/tty.h>
  29. #include <sys/filio.h>
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <vfork.h>
  33.  
  34. static short icon_image[] =
  35. {
  36. #   include "xvi.icn"
  37. };
  38.  
  39. mpr_static(iconpr, 64, 64, 1, icon_image);
  40.  
  41. static Frame frame;
  42. static Tty xviwin;
  43.  
  44. /*
  45.  * Handle keyboard or mouse input.
  46.  */
  47. static Notify_value
  48. ttyproc(win, event, na, type)
  49. Tty            win;
  50. Event            *event;
  51. Notify_arg        na;
  52. Notify_event_type    type;
  53. {
  54.     static Pixfont    *deffont = (Pixfont *) 0; /* default font */
  55.     register int    evtcode;
  56.     static char        seqbuf[(sizeof (unsigned int) * 12) + 7] =
  57.                         { PREFIXCHAR };
  58.     int            nchars;
  59.     bool_t        done;
  60.     static unsigned    buttonstate, prevx, prevy;
  61.     unsigned        mx, my;
  62.  
  63. #define    BUTTONMASK(e)        (1 << ((e) - BUT(1)))
  64.  
  65.     if (deffont == NULL) {
  66.     /*
  67.      * Get default font.
  68.      */
  69.     deffont = pf_default();
  70.     }
  71.  
  72.     evtcode = event_action(event);
  73.     mx = event_x(event) / deffont->pf_defaultsize.x;
  74.     my = event_y(event) / deffont->pf_defaultsize.y;
  75.     nchars = 0;
  76.     done = FALSE;
  77.     if (evtcode == LOC_DRAG && buttonstate == BUTTONMASK(MS_MIDDLE)) {
  78.     if (mx != prevx || my != prevy) {
  79.         /*
  80.          * Mouse drag event. Send a PREFIXCHAR,
  81.          * followed by 'm', followed by the starting
  82.          * row, finishing row, starting column &
  83.          * finishing column, in that order.
  84.          */
  85.         sprintf(&seqbuf[1], "m%x;%x;%x;%x;", prevy, my, prevx, mx);
  86.         nchars = strlen(seqbuf);
  87.         done = TRUE;
  88.         prevx = mx;
  89.         prevy = my;
  90.     }
  91.     } else if (event_is_down(event)) {
  92.     if (event_is_button(event)) {
  93.         switch (evtcode) {
  94.         case MS_MIDDLE:
  95.         prevx = mx;
  96.         prevy = my;
  97.         break;
  98.         case MS_RIGHT:
  99.         /*
  100.          * Right button pressed. We have to
  101.          * send a PREFIXCHAR, followed by 'p',
  102.          * followed by the position of the
  103.          * mouse cursor in character
  104.          * co-ordinates: y first, then x.
  105.          */
  106.         sprintf(&seqbuf[1], "p%x;%x;", my, mx);
  107.         nchars = strlen(seqbuf);
  108.         done = TRUE;
  109.         }
  110.         buttonstate |= BUTTONMASK(evtcode);
  111.     } else {
  112.         /*
  113.          * nchars is the number of characters we have
  114.          * to send to xvi.main. In most of the cases
  115.          * we have to deal with here, this will be 2.
  116.          */
  117.         nchars = 2;
  118.         done = TRUE;
  119.         switch (evtcode) {
  120.         case PREFIXCHAR:
  121.         seqbuf[1] = PREFIXCHAR;
  122.         break;
  123.         case KEY_RIGHT(7):
  124.         seqbuf[1] = 'H';
  125.         break;
  126.         case KEY_RIGHT(8):
  127.         seqbuf[1] = 'k';
  128.         break;
  129.         case KEY_RIGHT(9):
  130.         seqbuf[1] = CTRL('B');
  131.         break;
  132.         case KEY_RIGHT(10):
  133.         seqbuf[1] = '\b';
  134.         break;
  135.         case KEY_RIGHT(12):
  136.         seqbuf[1] = ' ';
  137.         break;
  138.         case KEY_RIGHT(13):
  139.         seqbuf[1] = 'L';
  140.         break;
  141.         case KEY_RIGHT(14):
  142.         seqbuf[1] = 'j';
  143.         break;
  144.         case KEY_RIGHT(15):
  145.         seqbuf[1] = CTRL('F');
  146.         break;
  147.         default:
  148.         nchars = 0;
  149.         done = FALSE;
  150.         }
  151.     }
  152.     } else if (event_is_up(event) && event_is_button(event)) {
  153.     if (evtcode == MS_RIGHT)
  154.         done = TRUE;
  155.     buttonstate &= ~BUTTONMASK(evtcode);
  156.     }
  157.     if (nchars > 0) {
  158.     ttysw_input(xviwin, seqbuf, nchars);
  159.     }
  160.     return done ?
  161.        NOTIFY_DONE :
  162.        notify_next_event_func(win, event, na, type);
  163. }
  164.  
  165. /*
  166.  * Read messages coming from back-end process.
  167.  */
  168. static Notify_value
  169. readsocket(client, fd)
  170. Notify_client    client;
  171. int        fd;
  172. {
  173.     char c;
  174.  
  175.     while (read(fd, &c, 1) == 1) {
  176.     if (c == 'q') {
  177.         (void) notify_set_input_func(client, NOTIFY_FUNC_NULL, fd);
  178.         window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);
  179.         window_destroy(frame);
  180.         return NOTIFY_DONE;
  181.     }
  182.  
  183.     }
  184.     return NOTIFY_DONE;
  185. }
  186.  
  187. static Notify_value
  188. sigign(client, signum, when)
  189. Notify_client        client;
  190. int            signum;
  191. Notify_signal_mode    when;
  192. {
  193.     return NOTIFY_IGNORED;
  194. }
  195.  
  196. /*
  197.  * Start up our back-end process and connect its standard input,
  198.  * output & error files to the tty subwindow we've created for it.
  199.  *
  200.  * We use a pair of connected stream sockets to communicate with it:
  201.  * it can reference its socket as file descriptor 3. Currently, this
  202.  * is only used by the back-end process to tell us when to exit (by
  203.  * sending the single character 'q').
  204.  */
  205. static void
  206. forkmain(argv)
  207. char    **argv;
  208. {
  209.     int        winfd;
  210.     int        commsock[2];
  211.     int        savefd[4];
  212.     int        nbflag;
  213.     int        i;
  214.     char    *progname;
  215.  
  216.  
  217.     for (i = 0; i <= 3; i++) {
  218.     while ((savefd[i] = dup(i)) <= 3) {
  219.         ;
  220.     }
  221.     }
  222.     if (socketpair(AF_UNIX, SOCK_STREAM, 0, commsock) != 0) {
  223.     fprintf(stderr, "%s: can't create socket\n", argv[0]);
  224.     exit(1);
  225.     }
  226.     winfd = (int) window_get(xviwin, TTY_TTY_FD);
  227.     if ((progname = strdup(argv[0])) == NULL) {
  228.     progname = "xvi.sunview";
  229.     }
  230.     argv[0] = XVI_MAINPROG;
  231.     switch (vfork()) {
  232.     case 0:        /* This is the child process. */
  233.     for (i = 0; i <= 2; i++) {
  234.         dup2(winfd, i);
  235.     }
  236.     dup2(commsock[1], 3);
  237.     ioctl(winfd, FIOCLEX, 0);
  238.     ioctl(commsock[0], FIOCLEX, 0);
  239.     ioctl(commsock[1], FIOCLEX, 0);
  240.     for (i = 0; i <= 3; i++) {
  241.         ioctl(savefd[i], FIOCLEX, 0);
  242.     }
  243.     execvp(argv[0], argv);
  244.     fprintf(stderr, "%s: can't execute %s\n", progname, argv[0]);
  245.     fflush(stderr);
  246.     _exit(1);
  247.  
  248.     case -1:
  249.     fprintf(stderr, "%s: vfork() failed\n", progname);
  250.     fflush(stderr);
  251.     _exit(1);
  252.  
  253.     default:    /* This is the parent process. */
  254.     /*
  255.      * We should only reach this point after the
  256.      * child has called execvp() (or died).
  257.      */
  258.     for (i = 0; i <= 3; i++) {
  259.         dup2(savefd[i], i);
  260.         close(savefd[i]);
  261.     }
  262.     close(commsock[1]);
  263.     /*
  264.      * commsock[0] is our end of the socketpair.
  265.      * We have to make it non-blocking & register
  266.      * an input handler for it.
  267.      */
  268.     nbflag = 1;
  269.     ioctl(commsock[0], FIONBIO, &nbflag);
  270.     (void) notify_set_input_func((Notify_client) xviwin,
  271.                     readsocket, commsock[0]);
  272.     }
  273. }
  274.  
  275. main(argc, argv)
  276. int    argc;
  277. char    **argv;
  278. {
  279.     Icon    xvicon;
  280.     char    *label;
  281.  
  282.     if ((label = strrchr(argv[0], '/')) == NULL) {
  283.     label = argv[0];
  284.     } else {
  285.     label++;
  286.     }
  287.     xvicon = icon_create(ICON_IMAGE, &iconpr, 0);
  288.     frame = window_create(NULL,                FRAME,
  289.                 FRAME_LABEL,        label,
  290.                 FRAME_ICON,            xvicon,
  291.                 FRAME_ARGC_PTR_ARGV,    &argc, argv,
  292.                 WIN_ERROR_MSG,        "Can't create window",
  293.                 FRAME_NO_CONFIRM,        TRUE,
  294.                 FRAME_SUBWINDOWS_ADJUSTABLE,
  295.                 FALSE,
  296.                 0);
  297.     xviwin = window_create(frame,            TTY,
  298.                 TTY_ARGV,            TTY_ARGV_DO_NOT_FORK,
  299.                 WIN_CONSUME_KBD_EVENTS,    WIN_RIGHT_KEYS,
  300.                 0,
  301.                 WIN_CONSUME_PICK_EVENTS,    WIN_MOUSE_BUTTONS,
  302.                 WIN_UP_EVENTS,
  303.                 LOC_DRAG,
  304.                 0,
  305.                 0);
  306.     (void) notify_set_signal_func((Notify_client) xviwin, sigign,
  307.               SIGHUP, NOTIFY_ASYNC);
  308.     (void) notify_set_signal_func((Notify_client) xviwin, sigign,
  309.               SIGINT, NOTIFY_ASYNC);
  310.     (void) notify_set_signal_func((Notify_client) xviwin, sigign,
  311.               SIGQUIT, NOTIFY_ASYNC);
  312.     forkmain(argv);
  313.     notify_interpose_event_func(xviwin, ttyproc, NOTIFY_SAFE);
  314.     window_main_loop(frame);
  315. }
  316.